#![no_std]          // 禁用标准库（bare-metal 环境）
#![no_main]         // 禁用 Rust 标准入口点

mod paging;
mod scheduler;
mod process;

use core::arch::asm;
use core::fmt::{self, Write};
use core::ptr;
use crate::paging::init_sv39_paging;
use crate::process::Process;
use crate::scheduler::Scheduler;

// UART 串口驱动（适用于 XiangShan KunmingHu 架构，假设基地址为 0x10000000）
struct Uart {
    base_addr: usize,
}

impl Uart {
    // 创建 UART 实例
    fn new(base_addr: usize) -> Self {
        Self { base_addr }
    }

    // 初始化 UART（简化版，适用于预配置好的硬件/模拟器）
    fn init(&self) {
        // 对于真实硬件，可能需要配置波特率、数据位等，此处省略
    }

    // 检查发送缓冲区是否为空
    fn is_tx_ready(&self) -> bool {
        // 读取 Line Status Register (LSR)，第 5 位表示发送缓冲区为空
        unsafe { ptr::read_volatile((self.base_addr + 5) as *const u8) & 0x20 != 0 }
    }

    // 发送单个字节
    fn send_byte(&self, byte: u8) {
        while !self.is_tx_ready() {} // 等待发送缓冲区就绪
        unsafe { ptr::write_volatile(self.base_addr as *mut u8, byte) } // 写入发送寄存器
    }
}

// 实现 fmt::Write 以支持格式化输出
impl fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            self.send_byte(c as u8); // 逐个字符发送
        }
        Ok(())
    }
}

// 内核入口点（XiangShan KunmingHu 启动时会跳转到该函数）
#[unsafe(no_mangle)] // 禁止 Rust 名称修饰，确保链接器能找到该符号
#[unsafe(link_section = ".text.entry")]
extern "C" fn _start() -> ! {
    // 初始化栈指针和其他必要设置
    unsafe {
        // 设置栈指针到RAM顶部
        asm!(
        "li sp, 0x88000000",  // 设置栈指针到RAM顶部附近
        "jal ra, rust_main",   // 跳转到Rust主函数
        );
    }

    loop {}
}

#[unsafe(no_mangle)] // 禁止 Rust 名称修饰，确保链接器能找到该符号
extern "C" fn rust_main() -> ! {

    // 初始化SV39分页
    // init_sv39_paging();


    // 使用SBI接口输出Hello World
    writeln!(SbiConsole, "Hello World via SBI!").unwrap();


    // 或者继续使用原有的UART输出
    let mut uart = Uart::new(0x10000000);
    uart.init();
    writeln!(uart, "Hello World via UART!").unwrap();




    // 可以选择使用SBI关机
    sbi_shutdown();
}

// Panic 处理函数（当程序 panic 时调用，bare-metal 环境必须实现）
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
    loop {} // 发生错误时无限循环
}

// SBI调用扩展ID
const SBI_CONSOLE_PUTCHAR: usize = 0x01;
const SBI_SHUTDOWN: usize = 0x08;

// SBI调用函数
fn sbi_call(ext_id: usize, func_id: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
    let ret;
    unsafe {
        asm!(
        "ecall",
        in("a0") arg0,
        in("a1") arg1,
        in("a2") arg2,
        in("a6") func_id,
        in("a7") ext_id,
        lateout("a0") ret,
        );
    }
    ret
}

// 通过SBI输出字符
fn sbi_console_putchar(ch: u8) {
    sbi_call(SBI_CONSOLE_PUTCHAR, 0, ch as usize, 0, 0);
}

// 通过SBI关闭系统
fn sbi_shutdown() -> ! {
    sbi_call(SBI_SHUTDOWN, 0, 0, 0, 0);
    loop {}
}


// 基于SBI的控制台输出结构体
struct SbiConsole;

impl fmt::Write for SbiConsole {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            sbi_console_putchar(c as u8);
        }
        Ok(())
    }
}

// 添加简单的进程切换函数
unsafe fn switch_to_process(process: &mut Process) {
    asm!(
    "mv sp, {sp}",  // 切换栈指针
    "ret",          // 返回到进程入口点
    sp = in(reg) process.stack_pointer,
    );
}

// 添加测试进程函数
fn process_task_1() -> ! {
    loop {
        writeln!(SbiConsole, "[Process 1] Running...").unwrap();
        // 模拟进程让出CPU
        unsafe {
            asm!("ecall");  // 通过系统调用触发调度
        }
    }
}

fn process_task_2() -> ! {
    loop {
        writeln!(SbiConsole, "[Process 2] Running...").unwrap();
        // 模拟进程让出CPU
        unsafe {
            asm!("ecall");  // 通过系统调用触发调度
        }
    }
}